﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;
using YJKGridTopologyCal.Geometries;

namespace YJKGridTopologyCal.Algorithm.Locate
{
	public class SimplePointInAreaLocator : IPointOnGeometryLocator
	{
		public static Location Locate(Coordinate p, IGeometry geom)
		{
			if (geom.IsEmpty)
			{
				return Location.Exterior;
			}
			if (SimplePointInAreaLocator.ContainsPoint(p, geom))
			{
				return Location.Interior;
			}
			return Location.Exterior;
		}

		private static bool ContainsPoint(Coordinate p, IGeometry geom)
		{
			if (geom is IPolygon)
			{
				return SimplePointInAreaLocator.ContainsPointInPolygon(p, (IPolygon)geom);
			}
			if (geom is IGeometryCollection)
			{
				IEnumerator<IGeometry> enumerator = new GeometryCollectionEnumerator((IGeometryCollection)geom);
				while (enumerator.MoveNext())
				{
					IGeometry geometry = enumerator.Current;
					if (geometry != geom && SimplePointInAreaLocator.ContainsPoint(p, geometry))
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool ContainsPointInPolygon(Coordinate p, IPolygon poly)
		{
			if (poly.IsEmpty)
			{
				return false;
			}
			ILinearRing ring = (ILinearRing)poly.ExteriorRing;
			if (!SimplePointInAreaLocator.IsPointInRing(p, ring))
			{
				return false;
			}
			for (int i = 0; i < poly.NumInteriorRings; i++)
			{
				ILinearRing ring2 = (ILinearRing)poly.GetInteriorRingN(i);
				if (SimplePointInAreaLocator.IsPointInRing(p, ring2))
				{
					return false;
				}
			}
			return true;
		}

		private static bool IsPointInRing(Coordinate p, ILinearRing ring)
		{
			return ring.EnvelopeInternal.Intersects(p) && CGAlgorithms.IsPointInRing(p, ring.Coordinates);
		}

		public SimplePointInAreaLocator(IGeometry geom)
		{
			this._geom = geom;
		}

		public Location Locate(Coordinate p)
		{
			return SimplePointInAreaLocator.Locate(p, this._geom);
		}

		private readonly IGeometry _geom;
	}
}
